package rest

import (
	"net/url"

	"gitee.com/youkelike/ziam/zapi/scheme"
	"gitee.com/youkelike/ziam/zsdk2/third_party/forked/gorequest"
	"gitee.com/youkelike/ziam/zutils/runtime"
	tlsutil "gitee.com/youkelike/ziam/zutils/tls"
)

type Interface interface {
	Verb(verb string) *Request
	Post() *Request
	Put() *Request
	Get() *Request
	Delete() *Request
	APIVersion() scheme.GroupVersion
}

// 第二层配置
type ClientContentConfig struct {
	// Username string
	// Password string

	SecretID  string
	SecretKey string
	// Server requires Bearer authentication. This client will not attempt to use
	// refresh tokens for an OAuth2 flow.
	// TODO: demonstrate an OAuth2 compatible client.
	BearerToken string

	// Path to a file containing a BearerToken.
	// If set, the contents are periodically read.
	// The last successfully read value takes precedence over BearerToken.
	BearerTokenFile string
	tlsutil.TLSClientConfig

	// AcceptContentTypes specifies the types the client will accept and is optional.
	// If not set, ContentType will be used to define the Accept header
	AcceptContentTypes string
	// ContentType specifies the wire format used to communicate with the server.
	// This value will be set as the Accept header on requests made to the server if
	// AcceptContentTypes is not set, and as the default content type on any object
	// sent to the server. If not set, "application/json" is used.
	ContentType  string
	GroupVersion scheme.GroupVersion
	Negotiator   runtime.ClientNegotiator
}

// HasBasicAuth returns whether the configuration has basic authentication or not.
// func (c *ClientContentConfig) HasBasicAuth() bool {
// 	return len(c.Username) != 0
// }

// HasTokenAuth returns whether the configuration has token authentication or not.
func (c *ClientContentConfig) HasTokenAuth() bool {
	return len(c.BearerToken) != 0 || len(c.BearerTokenFile) != 0
}

// HasKeyAuth returns whether the configuration has secretId/secretKey authentication or not.
func (c *ClientContentConfig) HasKeyAuth() bool {
	return len(c.SecretID) != 0 && len(c.SecretKey) != 0
}

type RESTClient struct {
	// 是对配置中的 host 解析并去掉 path 和 query 后的内容，
	base *url.URL
	// 在这里的 group 是 apiserver 或 authz
	group string
	// 是由配置中的 apiPath 和 version 组合而成
	versionedAPIPath string
	// content describes how a RESTClient encodes and decodes responses.
	content ClientContentConfig
	Client  *gorequest.SuperAgent
}

func newRESTClient(baseURL *url.URL, versionedAPIPath string,
	config ClientContentConfig, client *gorequest.SuperAgent) (*RESTClient, error) {
	return &RESTClient{
		base:             baseURL,                   // 是对配置中的 host 解析并去掉 path 和 query 后的内容，
		group:            config.GroupVersion.Group, // 在这里的 group 是 apiserver 或 authz
		versionedAPIPath: versionedAPIPath,          // 是由配置中的 apiPath 和 version 组合而成
		content:          config,
		Client:           client,
	}, nil
}

// Verb begins a Verb request.
func (c *RESTClient) Verb(verb string) *Request {
	return NewRequest(c).Verb(verb)
}

// Post begins a POST request. Short for c.Verb("POST").
func (c *RESTClient) Post() *Request {
	return c.Verb("POST")
}

// Put begins a PUT request. Short for c.Verb("PUT").
func (c *RESTClient) Put() *Request {
	return c.Verb("PUT")
}

// Get begins a GET request. Short for c.Verb("GET").
func (c *RESTClient) Get() *Request {
	return c.Verb("GET")
}

// Delete begins a DELETE request. Short for c.Verb("DELETE").
func (c *RESTClient) Delete() *Request {
	return c.Verb("DELETE")
}

// APIVersion returns the APIVersion this RESTClient is expected to use.
func (c *RESTClient) APIVersion() scheme.GroupVersion {
	return c.content.GroupVersion
}
